package com.nwpusp.display.views;

import java.util.ArrayList;
import java.util.Timer;

import com.nwpusp.controller.GameController;
import com.nwpusp.display.GlobalVar;
import com.nwpusp.display.MainActivity;
import com.nwpusp.display.resmgr.AnimalProcessViewResManager;
import com.nwpusp.display.resmgr.AnimalViewResManager;
import com.nwpusp.display.resmgr.BarrierViewResManager;
import com.nwpusp.display.resmgr.PropViewResManager;
import com.nwpusp.display.views.components.Animal;
import com.nwpusp.display.views.components.BackGround;
import com.nwpusp.display.views.components.Button;
import com.nwpusp.display.views.components.CountDown;
import com.nwpusp.display.views.components.GameBackGround;
import com.nwpusp.display.views.components.GameMillisecondClock;
import com.nwpusp.display.views.components.GameProcessBar;
import com.nwpusp.display.views.components.GameProcessBarHeader;
import com.nwpusp.display.views.components.HurdleLeft;
import com.nwpusp.display.views.components.HurdleRight;
import com.nwpusp.display.views.components.Props;
import com.nwpusp.model.Entity;
import com.nwpusp.model.GameModel;
import com.nwpusp.model.barrier.Barrier;
import com.nwpusp.model.characters.CharacterVisitor;
import com.nwpusp.model.characters.GameCharacter;
import com.nwpusp.model.location.Axis;
import com.nwpusp.model.location.Size;
import com.nwpusp.model.players.Player;
import com.nwpusp.model.props.Prop;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.GestureDetector;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class GameView  extends SurfaceView implements SurfaceHolder.Callback, OnGestureListener,  OnTouchListener {
	
	private GestureDetector mGestureDetector;
	private MainActivity mainActivity;
	private GameController controller = null;
	private GameModel model = null;
	private Paint myPaint;
	private ArrayList<Button> al_Btn = new ArrayList<Button>();
	private Button upBtn;
	private Button downBtn;
	private Button throwBtn;
	private GameBackGround gameViewBackGround;
	private GameProcessBar gameProcessBar;
	// private GameProcessBarHeader gameProcessBarHeader;
	private float gameViewBackGround_X;
	private float gameViewBackGround_Y;
	private float gameProcessBarHeader_X;
	private float gameProcessBarHeader_Y;
	private float myClock_X;
	private float myClock_Y;
	private float upBtn_X;
	private float upBtn_Y;
	private float downBtn_X;
	private float downBtn_Y;
	private float throwBtn_X;
	private float throwBtn_Y;
	private float ratio;
	private Timer timer = null;  
	private MyTimerTask task = null;  
	public long tickNum = 0; 
	private float btnScale = (float)0.1;
	private float gameProcessBarScale = (float)0.8;
	private float countDownScale = (float)0.2;
	private Size scenarioSize = null;
	
	public  GameView(MainActivity mainActivity,GameController controller,GameModel model){
		super(mainActivity);
		this.responseToStart = false;
		this.mainActivity = mainActivity;
		this.controller = controller;
		this.model = model;
		SurfaceHolder holder = getHolder();  
	    holder.addCallback(this); 
	    myPaint = new Paint();
	    
		this.setLongClickable(true);   
	    this.setOnTouchListener(this); 
	    this.mGestureDetector = new GestureDetector(this); 
		mGestureDetector.setIsLongpressEnabled(true);   
		
		//ratio = GlobalVar.screenWidth*GlobalVar.half / 1066;
		ratio = GlobalVar.screenWidth*GlobalVar.half / 10660;

		gameViewBackGround = new GameBackGround(mainActivity,1);
		gameProcessBar = new GameProcessBar(mainActivity,gameProcessBarScale);
		mainActivity.countDown.setScale(countDownScale);
		upBtn = new Button(mainActivity, btnScale, GlobalVar.TRACK_UP);
		downBtn = new Button(mainActivity, btnScale, GlobalVar.TRACK_DOWN);
		throwBtn = new Button(mainActivity, btnScale, GlobalVar.THROW);
		// gameProcessBarHeader = new GameProcessBarHeader(mainActivity, gameProcessBar.height, 1);
		
		if(animalHeadGenerator == null) {
			animalHeadGenerator = new AnimalProcessHeadGenerator(this.mainActivity, gameProcessBar.height);
		}
		
		caculateLocation();
		
		gameViewBackGround.setLocation(gameViewBackGround_X,gameViewBackGround_Y);
		mainActivity.gameMillisecondClock.setLocation(myClock_X, myClock_Y);
		upBtn.setLocation(upBtn_X,upBtn_Y);
		downBtn.setLocation(downBtn_X,downBtn_Y);
		throwBtn.setLocation(throwBtn_X,throwBtn_Y);
		GameProcessBarHeader.setLocation(gameProcessBarHeader_X, gameProcessBarHeader_Y);
		
		al_Btn.add(upBtn);
		al_Btn.add(downBtn);
		al_Btn.add(throwBtn);
		
		scenarioSize = this.model.getScenario().getSize();
	}
	
	private class AnimalGenerator implements CharacterVisitor {

		private AnimalViewResManager avrm = new AnimalViewResManager();
		private Object[] params = new Object[5];
		MainActivity actitivy = null;
		float ratio;
		
		public AnimalGenerator(MainActivity act, float ratio) {
			this.actitivy = act;
			this.ratio = ratio;
		}
		
		public void Stock(View v) {
			avrm.Stock(v);
		}
		
		@Override
		public Object visitCat(GameCharacter c) {
			params[0] = actitivy;
			params[1] = Integer.valueOf((int)(c.getSize().getZ() * ratio));		// height
			params[2] = Integer.valueOf(1);										// index
			params[3] = Integer.valueOf(c.getStatus());							// status
			params[4] = c.getName();											// name
			return avrm.Fetch(params);
		}

		@Override
		public Object visitCow(GameCharacter c) {
			params[0] = actitivy;
			params[1] = Integer.valueOf((int)(c.getSize().getZ() * ratio));		// height
			params[2] = Integer.valueOf(2);										// index
			params[3] = Integer.valueOf(c.getStatus());							// status
			params[4] = c.getName();											// name
			return avrm.Fetch(params);
		}

		@Override
		public Object visitChicken(GameCharacter c) {
			params[0] = actitivy;
			params[1] = Integer.valueOf((int)(c.getSize().getZ() * ratio));		// height
			params[2] = Integer.valueOf(3);										// index
			params[3] = Integer.valueOf(c.getStatus());							// status
			params[4] = c.getName();											// name
			return avrm.Fetch(params);
		}

		@Override
		public Object visitHorse(GameCharacter c) {
			params[0] = actitivy;
			params[1] = Integer.valueOf((int)(c.getSize().getZ() * ratio));		// height
			params[2] = Integer.valueOf(4);										// index
			params[3] = Integer.valueOf(c.getStatus());							// status
			params[4] = c.getName();											// name
			return avrm.Fetch(params);
		}

		@Override
		public Object visitPig(GameCharacter c) {
			params[0] = actitivy;
			params[1] = Integer.valueOf((int)(c.getSize().getZ() * ratio));		// height
			params[2] = Integer.valueOf(5);										// index
			params[3] = Integer.valueOf(c.getStatus());							// status
			params[4] = c.getName();											// name
			return avrm.Fetch(params);
		}

		@Override
		public Object visitSheep(GameCharacter c) {
			params[0] = actitivy;
			params[1] = Integer.valueOf((int)(c.getSize().getZ() * ratio));		// height
			params[2] = Integer.valueOf(6);										// index
			params[3] = Integer.valueOf(c.getStatus());							// status
			params[4] = c.getName();											// name
			return avrm.Fetch(params);
		}
	}
	
	private class AnimalProcessHeadGenerator implements CharacterVisitor {

		private AnimalProcessViewResManager apvrm = new AnimalProcessViewResManager();
		private Object[] params = new Object[3];
		MainActivity actitivy = null;
		Float height = null;
		
		public AnimalProcessHeadGenerator(MainActivity a, float h) {
			this.actitivy = a;
			this.height = Float.valueOf(h);
		}
		
		@Override
		public Object visitCat(GameCharacter c) {
			params[0] = actitivy;								// context view
			params[1] = height;									// height
			params[2] = Integer.valueOf(1);						// index	
			return apvrm.Fetch(params);
		}

		@Override
		public Object visitCow(GameCharacter c) {
			params[0] = actitivy;								// context view
			params[1] = height;									// height
			params[2] = Integer.valueOf(2);						// index	
			return apvrm.Fetch(params);
		}

		@Override
		public Object visitChicken(GameCharacter c) {
			params[0] = actitivy;								// context view
			params[1] = height;									// height
			params[2] = Integer.valueOf(3);						// index	
			return apvrm.Fetch(params);
		}

		@Override
		public Object visitHorse(GameCharacter c) {
			params[0] = actitivy;								// context view
			params[1] = height;									// height
			params[2] = Integer.valueOf(4);						// index	
			return apvrm.Fetch(params);
		}

		@Override
		public Object visitPig(GameCharacter c) {
			params[0] = actitivy;								// context view
			params[1] = height;									// height
			params[2] = Integer.valueOf(5);						// index	
			return apvrm.Fetch(params);
		}

		@Override
		public Object visitSheep(GameCharacter c) {
			params[0] = actitivy;								// context view
			params[1] = height;									// height
			params[2] = Integer.valueOf(6);						// index	
			return apvrm.Fetch(params);
		}
		
	}
	
	private class PropGenerator {
		private PropViewResManager pvrm = new PropViewResManager();
		private Object[] params = new Object[3];
		MainActivity actitivy = null;
		float newHeight;
		
		public PropGenerator(MainActivity act, float newHeight) {
			this.actitivy = act;
			this.newHeight = newHeight;
		}
		
		public Props Fetch() {
			params[0] = actitivy;
			params[1] = Float.valueOf(newHeight);		// scale
			return (Props) pvrm.Fetch(params);
		}
		
		public void Stock(Props p) {
			pvrm.Stock(p);
		}
	}
	
	private class BarrierGenerator {
		private BarrierViewResManager pvrm = new BarrierViewResManager();
		private Object[] params = new Object[3];
		MainActivity actitivy = null;
		float newHeight;
		
		public BarrierGenerator(MainActivity act, float newHeight) {
			this.actitivy = act;
			this.newHeight = newHeight;
		}
		
		public View Fetch(BarrierViewResManager.BarrierType type) {
			params[0] = actitivy;						// context view
			params[1] = Float.valueOf(newHeight);		// scale
			params[2] = type;
			return pvrm.Fetch(params);
		}
		
		public void Stock(View b) {
			pvrm.Stock(b);
		}
	}
	
	private AnimalGenerator animalGenerator = null;
	private PropGenerator propGenerator = null;
	private BarrierGenerator barrierGenerator = null;
	private AnimalProcessHeadGenerator animalHeadGenerator = null;
	
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.drawBitmap(gameViewBackGround.draw(),gameViewBackGround.x,gameViewBackGround.y,myPaint);
		canvas.drawBitmap(gameProcessBar.draw(),gameProcessBar.x,gameProcessBar.y,myPaint);
		// canvas.drawBitmap(gameProcessBarHeader.draw(),gameProcessBarHeader.x,gameProcessBarHeader.y,myPaint);
		
// Draw Process bar heads {
		ArrayList<Player> plist = this.model.getPlayerManager().getPlayerList();
		int totalDistance = scenarioSize.getX();
		for(Player p : plist) {
			GameCharacter ch = p.getCh();
			GameProcessBarHeader animalHeader = (GameProcessBarHeader)ch.Visited(animalHeadGenerator);
			int runDistance = ch.getPosition().getX();
			animalHeader.setDistance(runDistance, totalDistance, gameProcessBar.width);
			canvas.drawBitmap(animalHeader.draw(), animalHeader.x, animalHeader.y, myPaint);
		}
// } Draw Process bar heads
		
		
		canvas.drawBitmap(mainActivity.gameMillisecondClock.draw(),
				mainActivity.gameMillisecondClock.x,mainActivity.gameMillisecondClock.y,myPaint);
		if(GlobalVar.drawCountDown)
			canvas.drawBitmap(mainActivity.countDown.draw(), mainActivity.countDown.x, mainActivity.countDown.y,myPaint);
		canvas.drawBitmap(upBtn.draw(),upBtn.x,upBtn.y,myPaint);	
		canvas.drawBitmap(downBtn.draw(),downBtn.x,downBtn.y,myPaint);
		canvas.drawBitmap(throwBtn.draw(),throwBtn.x,throwBtn.y,myPaint);
		
		if(animalGenerator == null) {
			animalGenerator = new AnimalGenerator(this.mainActivity, this.ratio);
		}
		
		ArrayList<Entity> drawEnts = model.getDispEntities();
		if(drawEnts != null) {
			for(Entity entity:drawEnts){
				Axis pos = entity.getPosition();
				Size size = entity.getSize();
				float location [] = TransAxis(pos,size);
				if(entity instanceof GameCharacter) {
					//int status = entity.getStatus();
					// animal1.setStatus(status);
					Animal anim = (Animal)((GameCharacter)entity).Visited(animalGenerator);
					if(anim != null) {
						anim.setLocation(location[0],location[1]);
						canvas.drawBitmap(anim.draw(tickNum),anim.x,anim.y,myPaint);
						animalGenerator.Stock(anim);
					}
					else {
						Log.d("Justin Animal", "null accure");
					}
				}
				else if(entity instanceof Prop) {
					if(propGenerator == null) {
						propGenerator = new PropGenerator(this.mainActivity, this.ratio * (size.getZ()));
					}
					Props props = propGenerator.Fetch();
					props.setLocation(location[0], location[1]);
					canvas.drawBitmap(props.draw(),props.x,props.y,myPaint);
					propGenerator.Stock(props);
				}
				else if(entity instanceof Barrier) {
					if(barrierGenerator == null) {
						barrierGenerator = new BarrierGenerator(this.mainActivity, this.ratio * (size.getZ()));
					}
					HurdleLeft left = (HurdleLeft) barrierGenerator.Fetch(BarrierViewResManager.BarrierType.left);
					HurdleRight right = (HurdleRight) barrierGenerator.Fetch(BarrierViewResManager.BarrierType.right);
					if(left != null && right != null) {
						left.setLocation(location[0], location[1]);
						canvas.drawBitmap(left.draw(), left.x, left.y, myPaint);
						right.setLocation(location[0], location[1]);
						canvas.drawBitmap(right.draw(), right.x, right.y, myPaint);
						barrierGenerator.Stock(left);
						barrierGenerator.Stock(right);
					}
				}		
			}
		}
		if(!responseToStart) {
			responseToStart = true;
			this.mainActivity.responseToStart();
		}
	}
	
	private boolean responseToStart = false;
	
	private void caculateLocation(){
		gameViewBackGround_X = 0;
		gameViewBackGround_Y = 0;
		gameProcessBarHeader_X = gameProcessBar.x;
		gameProcessBarHeader_Y = gameProcessBar.y;
		myClock_X = (GlobalVar.screenWidth - mainActivity.gameMillisecondClock.width)*GlobalVar.half;
		myClock_Y = GlobalVar.screenHeight *GlobalVar.one_twenty;
		throwBtn_X = GlobalVar.one_fifty * GlobalVar.screenWidth;
		throwBtn_Y = (GlobalVar.screenHeight - upBtn.height)*GlobalVar.half;
		upBtn_X = throwBtn_X;
		upBtn_Y = throwBtn_Y + throwBtn.height + GlobalVar.screenHeight*GlobalVar.one_twenty;
		downBtn_X = throwBtn_X;
		downBtn_Y = upBtn_Y + upBtn.height + GlobalVar.screenHeight*GlobalVar.one_twenty;
	}
	
	private float[] TransAxis(Axis pos,Size size){
		int x = pos.getX();
		int y = pos.getY();
		int z = pos.getZ();
		float xf = x*ratio;
		float yf = y*ratio;
		float zf = z*ratio;
		int length = size.getX();
		int deepth = size.getY();
		int height = size.getZ();
		float lengthf = length*ratio;
		float deepthf = deepth*ratio;
		float heightf = height*ratio;
		float Location []  = new float[2];
		//Location[0] = xf-lengthf;
		Location[0] = xf;
		if(zf==0){
			Location[1] = GlobalVar.screenHeight-yf-heightf-gameProcessBar.height;
		}
		else{
			Location[1] = GlobalVar.screenHeight-yf-heightf-zf-gameProcessBar.height;
		}
		return Location;
	}
	
	
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
	}
	public void surfaceCreated(SurfaceHolder holder) {
		 timer = new Timer();  
	     task = new MyTimerTask(this,holder);  
	     timer.schedule(task, 0, 100);  

	}
	public void surfaceDestroyed(SurfaceHolder holder) {
		if(timer != null) {  
			timer.cancel();  
	        timer = null;  
	    }  
	    task = null;   
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		//float x1 = e1.getX();
		//float x2 = e2.getX();
		float y1 = e1.getY();
		float y2 = e2.getY();
		if(flingUp(y1,y2)){
			mainActivity.mhadnler.sendEmptyMessage(GlobalVar.FLING_UP);
		}
		else if(flingDown(y1,y2)){
			mainActivity.mhadnler.sendEmptyMessage(GlobalVar.FLING_DOWN);
		}
		return false;
	}
	
	private boolean flingUp(float y1,float y2){
		if(y1-y2>GlobalVar.screenHeight*GlobalVar.one_ten)
			return true;
		else
			return false;
	}
	private boolean flingDown(float y1,float y2){
		if(y2-y1>GlobalVar.screenHeight*GlobalVar.one_ten)
			return true;
		else
			return false;
	}

	

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {return false;}
	@Override
	public void onShowPress(MotionEvent e) {}
	@Override
	public void onLongPress(MotionEvent e) {}
	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		float x = e.getX();
		float y = e.getY();
		for(Button btn :al_Btn){
			if(btn.isClick(x,y)){
				mainActivity.mhadnler.sendEmptyMessage(btn.btnIndex);
			}
		}
		return false;
	}
	@Override
	public boolean onTouch(View v, MotionEvent event) {return mGestureDetector.onTouchEvent(event);}
	@Override
	public boolean onDown(MotionEvent e) {return false;}
	/*public boolean onTouchEvent(MotionEvent event) {
		return super.onTouchEvent(event);
	}*/

	
}
